package com.sie.bank;


import java.io.UnsupportedEncodingException;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import com.sie.zhq.tool.ByteTool;
import com.sie.zhq.tool.StringUtil;


/**
 * x9.8输入PIN标准
 * @author zouhuaqiu
 * @date 2014-08-21
 * 
 */
public class EncryptUnit {

	public static final String Algorithm3DES = "DESede";
	public static final String AlgorithmDES = "DES";

	private byte[] masterKey;
	private byte[] workingKey;
	private String card_no;
    /**
     * 设置主密钥
     * @param masterKey
     * @return
     */
	public EncryptUnit setMasterKey(byte[] masterKey) {

		this.masterKey = masterKey;
		return this;
	}
    /**
     * 工作密钥
     * @param workingKey
     * @return
     */
	public EncryptUnit setWorkingKey(byte[] workingKey) {

		this.workingKey = workingKey;
		return this;
	}
    /**
     * 卡号
     * @param card_no
     * @return
     */
	public EncryptUnit setCardNo(String card_no) {

		this.card_no = card_no;
		return this;
	}
    /**
     * 模拟输入PIN
     * @param PIN
     * @return
     */
	public byte[] inputPIN(String PIN) {

		String pin_str = builtPINStr(PIN);
		String card_str = builtCardStr(card_no);

		byte[] real_workingKey = decryptMode(workingKey, Algorithm3DES,
				masterKey);

		byte[] ex = ByteTool.hexStr2Bytes(StringUtil.XOR(pin_str, card_str));

		return encryptMode(ex, real_workingKey, Algorithm3DES);

	}

	/**
	 * 解密加密串
	 * @param ciphertext
	 * @return
	 */
	public String decrypt(byte[] ciphertext) {

		byte[] real_workingKey = decryptMode(workingKey, Algorithm3DES,
				masterKey);
		byte[] src = decryptMode(ciphertext, Algorithm3DES, real_workingKey);
		String card_str = builtCardStr(card_no);
		byte[] tmp =  ByteTool.hexStr2Bytes(StringUtil.XOR(ByteTool.byte2hex(src), card_str));
		String str = ByteTool.byte2hex(tmp);
		int length = Integer.valueOf(str.substring(0, 2));
		String pin = str.substring(2, length + 2);
		return pin;
	}
   /**
    * 生成PIN的加密串
    * @param PIN
    * @return
    */
	private static String builtPINStr(String PIN) {

		int length = PIN.length();
		String len = String.valueOf(length);
		len = (len.length() == 1) ? ("0" + len) : len;
		StringBuffer sb = new StringBuffer();
		sb.append(len);
		sb.append(PIN);
		for (; sb.length() < 16;) {
			sb.append("F");
			
		}
		System.out.println("pin:" + sb);
		return sb.toString();

	}
    /**
     * 生成卡号的加密串
     * @param card_no
     * @return
     */
	private static String builtCardStr(String card_no) {

		StringBuffer sb = new StringBuffer();
		sb.append("0000");
		StringBuffer card_buff = new StringBuffer(card_no);
		card_buff = card_buff.reverse();
		card_buff = new StringBuffer(card_buff.substring(1, 13)).reverse();
		char[] ch = card_buff.toString().toCharArray();
		for (int i = 0; sb.length() < 16; i++) {
			sb.append(ch[i]);
		}
		return sb.toString();

	}

	/**
	 * ʹ
	 * 
	 * @param src
	 * @param key
	 *     
	 * @param Algorithm
	 *            
	 * @return
	 */

	public static byte[] encryptMode(byte[] src, byte[] key, String Algorithm) {
		try {
			SecretKey deskey = new SecretKeySpec(
					Algorithm.equals(Algorithm3DES) ? build3DesKey(key)
							: build3DesKey(key), Algorithm); // ������?
			Cipher c1 = Cipher.getInstance("DESede/ECB/NoPadding");// ʵ�������?���ܵ�Cipher������
			c1.init(Cipher.ENCRYPT_MODE, deskey); // ��ʼ��Ϊ����ģʽ
			return c1.doFinal(src);
		} catch (java.security.NoSuchAlgorithmException e1) {
			e1.printStackTrace();
		} catch (javax.crypto.NoSuchPaddingException e2) {
			e2.printStackTrace();
		} catch (Exception e3) {
			e3.printStackTrace();
		}
		return null;
	}

	/**
	 * 
	 * 
	 * @param src
	 * 
	 * @return
	 */
	public static byte[] decryptMode(byte[] src, String Algorithm, byte[] key) {
		try {
			SecretKey deskey = new SecretKeySpec(build3DesKey(key), Algorithm);
			Cipher c1 = Cipher.getInstance("DESede/ECB/NoPadding");
			c1.init(Cipher.DECRYPT_MODE, deskey); 
			return c1.doFinal(src);
		} catch (java.security.NoSuchAlgorithmException e1) {
			e1.printStackTrace();
		} catch (javax.crypto.NoSuchPaddingException e2) {
			e2.printStackTrace();
		} catch (Exception e3) {
			e3.printStackTrace();
		}
		return null;
	}

	/**
	 * 
	 * 生成3des加密串，16字节长的会自动补成24字节
	 * @param keyStr 
	 * 
	 * @return
	 * 
	 * @throws UnsupportedEncodingException
	 */
	public static byte[] build3DesKey(byte[] temp)
			throws UnsupportedEncodingException {
		byte[] key = new byte[24];
		System.arraycopy(temp, 0, key, 0, temp.length);
		if (temp.length == 16) {
			for (int i = 0; i < 8; i++) {
				key[16 + i] = temp[i];
			}
		}
		return key;
	}

	
	

	/**
	 * DES加密数据非填充方式
	 * 
	 * @param hexKey
	 * @param hexData
	 * @param mode
	 * @return
	 * @throws Exception
	 */
	public static String decEncNoPaddingDES(String hexKey, String hexData,
			int mode) throws Exception {
		SecretKey desKey = new SecretKeySpec(ByteTool.hexStr2Bytes(hexKey),
				AlgorithmDES);

		Cipher cp = Cipher.getInstance("DES/ECB/NoPadding");
		cp.init(mode, desKey);
		byte[] bytes = cp.doFinal(ByteTool.hexStr2Bytes(hexData));

		return ByteTool.byte2hex(bytes);
	}

	/**
	 * 用key生成加密
	 * @param hexKey
	 * @param hexData
	 * @return
	 * @throws Exception
	 */
	
	public static String encrypt(String hexKey, String hexData)
			throws Exception {
		SecretKey desKey = new SecretKeySpec(build3DesKey(ByteTool.hexStr2Bytes(hexKey)),
				AlgorithmDES);

		Cipher cp = Cipher.getInstance("DES");
		cp.init(Cipher.ENCRYPT_MODE, desKey);
		byte[] bytes = cp.doFinal(ByteTool.hexStr2Bytes(hexData));

		return ByteTool.byte2hex(bytes);
	}

	/**
	 * 3Des加密非填充
	 * 
	 * @param hexKey
	 * @param hexData
	 * @return
	 * @throws Exception
	 */
	public static String encryptDesSede(String hexKey, String hexData)
			throws Exception {
		SecretKey desKey = new SecretKeySpec(build3DesKey(ByteTool.hexStr2Bytes(hexKey)),
				Algorithm3DES);

		Cipher cp = Cipher.getInstance("DESede/ECB/NoPadding");
		cp.init(Cipher.ENCRYPT_MODE, desKey);
		byte[] bytes = cp.doFinal(ByteTool.hexStr2Bytes(hexData));

		return ByteTool.byte2hex(bytes);
	}
	
	
}
